package com.ynet.middleground.approve.service.impl;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.validation.Valid;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;

import com.alibaba.fastjson.JSON;
import com.google.common.base.Throwables;
import com.ynet.core.codec.mark.util.ObjectUtil;
import com.ynet.core.common.ServiceResult;
import com.ynet.core.exception.BusinessException;
import com.ynet.core.log.IfpLogger;
import com.ynet.middleground.approve.bean.*;
import com.ynet.middleground.approve.constant.OperatingTypeEnum;
import com.ynet.middleground.approve.constant.WorkflowConstants;
import com.ynet.middleground.approve.dto.*;
import com.ynet.middleground.approve.entity.ArCommentExt;
import com.ynet.middleground.approve.model.ProcessRuntimeModel;
import com.ynet.middleground.approve.model.ProcessTaskModel;
import com.ynet.middleground.approve.model.UserCenterModel;
import com.ynet.middleground.approve.service.ProcessTaskService;
import com.ynet.middleground.user.dto.UserBaseInformationDto;
import com.ynet.middleground.user.dto.UserInfoDto;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;

/**
 * @author liulx
 * @description 流程任务处理相关接口服务类
 * @date 2019-10-15 14:07
 */
@Api(value = "审批流程中，主要为任务处理相关接口服务", tags = {"流程任务处理相关接口服务"})
@Produces({MediaType.APPLICATION_JSON + "; " + "charset=UTF-8"})
@Consumes({MediaType.APPLICATION_JSON + "; " + "charset=UTF-8"})
@Path("tasks")
@Service(timeout = 6000, version = "0.0.1")
public class ProcessTaskServiceImpl implements ProcessTaskService {

    @Autowired
    private ProcessTaskModel processTaskModel;

    @Autowired
    private UserCenterModel userCenterModel;

    @Autowired
    private ProcessRuntimeModel processRuntimeModel;

    /**
     * 根据流程实例ID，查询当前活动任务 <br />
     * 如果是并行任务（比如会签），可能会有多个，所以用集合接受 <br />
     * 
     * @param req 查询当前活动任务请求对象: {流程实例ID}
     * @return 当前任务活动信息
     */
    @POST
    @Path("active-task")
    @ApiOperation(value = "查询流程当前活动任务", notes = "根据流程实例ID查询流程当前活动任务，查询当前审批流程到哪个审批环节")
    @ApiImplicitParam(name = "requestObj", dataType = "ProcessInstanceReq", paramType = "body", required = true)
    @Override
    public ServiceResult<List<TaskDTO>> getActiveTaskByInstanceId(ProcessInstanceReq req) {
        ServiceResult<List<TaskDTO>> result = new ServiceResult<>();
        try {
            List<TaskDTO> resultList = processTaskModel.getActiveTaskByInstanceId(req);
            result.setResult(resultList);
        } catch (BusinessException be) {
            result.setError(be.getCode(), be.getMessage());
        } catch (Exception e) {
            IfpLogger.error(Thread.currentThread().getStackTrace()[1].getMethodName(),
                "activiti根据流程实例ID查询流程当前活动任务异常，case: {}", Throwables.getStackTraceAsString(e));
            result.setError("ECAP0000", "服务异常，请联系系统管理员");
            return result;
        }
        return result;
    }

    /**
     * 分页查询审核任务列表
     *
     * @param queryTaskReqPager 分页查询任务列表请求对象: {处理人,候选用户,候选用户组, 查询类型}
     * @return 审核任务列表
     */
    @POST
    @Path("list")
    @ApiOperation(value = "分页查询审核任务列表", notes = "查询用户已审核、待审核任务列表", produces = "application/json")
    @ApiImplicitParam(name = "requestObj", dataType = "QueryTaskReqPager", paramType = "body", required = true)
    @Override
    public ServiceResult<List<TaskDTO>> listTaskByPage(QueryTaskReqPager queryTaskReqPager) {
        ServiceResult<List<TaskDTO>> result = new ServiceResult<>();
        int type = queryTaskReqPager.getType();
        try {
            List<TaskDTO> taskList;
            // 待审批列表
            if (type == 0) {
                taskList = processTaskModel.listAuditingTaskByPage(queryTaskReqPager);
            } else if (type == 1) {
                // 已审批列表
                taskList = processTaskModel.listAuditedTaskByPage(queryTaskReqPager);
            } else {
                result.setError("ECAP0409", "查询类型参数异常");
                return result;
            }

            result.setResult(taskList);
            result.setPagerInfo(queryTaskReqPager.getPagerInfo());
        } catch (BusinessException be) {
            result.setError(be.getCode(), be.getMessage());
        } catch (Exception e) {
            IfpLogger.error(Thread.currentThread().getStackTrace()[1].getMethodName(), "activiti分页查询审核任务列表异常,case:{}",
                Throwables.getStackTraceAsString(e));
            result.setError("ECAP0000", "服务异常，请联系系统管理员");
        }
        return result;
    }

    /**
     * 分页查询审核任务列表(移动端专用)
     *
     * @param queryTaskReqPager 分页查询任务列表请求对象
     * @return 审核任务列表
     * @Author liwq
     */
    @POST
    @Path("listTaskByPageForMobile")
    @ApiOperation(value = "分页查询审核任务列表（移动端专用）", notes = "分页查询审核任务列表（移动端专用）", produces = "application/json")
    @ApiImplicitParam(name = "requestObj", dataType = "QueryTaskForMobileReqPager", paramType = "body", required = true)
    @Override
    public ServiceResultMobile<List<TaskDTOForMobile>>
        listTaskByPageForMobile(QueryTaskForMobileReqPager queryTaskReqPager) {
        ServiceResultMobile<List<TaskDTOForMobile>> result = new ServiceResultMobile<>();
        PagerInfoCount pagerInfoCount = new PagerInfoCount();
        int type = queryTaskReqPager.getType();
        try {
            List<TaskDTOForMobile> taskList = null;
            // 0:未完成，待办任务；
            if (type == 0) {
                taskList = processTaskModel.listAuditingTaskByPageForMobile(queryTaskReqPager, pagerInfoCount);
            } else if (type == 1) {
                // 1:完结，自己已经审批完，并且整个流程也结束了；
                taskList = processTaskModel.listAuditedTaskByPageForMobile(queryTaskReqPager, pagerInfoCount);
            } else if (type == 2) {
                // 2：已批，自己已经审批完，但是整个流程并未结束；
                taskList = processTaskModel.listAuditedTaskByPageForMobile(queryTaskReqPager, pagerInfoCount);
            } else {
                result.setError("ECAP0409", "查询类型参数异常");
                return result;
            }

            result.setResult(taskList);
            result.setPagerInfo(pagerInfoCount);
        } catch (BusinessException be) {
            result.setError(be.getCode(), be.getMessage());
        } catch (Exception e) {
            IfpLogger.error(Thread.currentThread().getStackTrace()[1].getMethodName(), "activiti分页查询审核任务列表异常,case:{}",
                Throwables.getStackTraceAsString(e));
            result.setError("ECAP0000", "服务异常，请联系系统管理员");
        }
        return result;
    }

    /**
     * 转办任务
     *
     * @param transferTaskReq 任务处理请求对象: {taskId, assignee, receiver}
     * @return 转办结果标志 true/false
     */
    @POST
    @ApiOperation(value = "转办任务", notes = "转办任务给其他人处理，如果当前任务节点是多个人，需要先调用任务拾取才能调用转办", produces = "application/json")
    @ApiImplicitParam(name = "requestObj", dataType = "TransferTaskReq", paramType = "body", required = true)
    @Override
    public ServiceResult transferTask(TransferTaskReq transferTaskReq) {
        ServiceResult result = new ServiceResult<>();
        try {
            processTaskModel.transferTask(transferTaskReq);
        } catch (BusinessException be) {
            result.setError(be.getCode(), be.getMessage());
        } catch (Exception e) {
            IfpLogger.error(Thread.currentThread().getStackTrace()[1].getMethodName(), "转办任务执行业务异常,case:{}",
                Throwables.getStackTraceAsString(e));
            result.setError("ECAP0000", "服务异常，请联系系统管理员");
        }
        return result;
    }

    /**
     * 拾取(认领)任务，指定用户组里的人都可以拾取该任务 <br />
     *
     * @param processTaskReq 任务处理请求对象: {taskId, assignee}
     * @return 转办结果标志，以success 字段值标识 true/false
     */
    @POST
    @Path("claim")
    @ApiOperation(value = "拾取（认领）任务", notes = "指定用户组里的人和指定的候选人都可以拾取该任务，一部分人都可以查询到待办任务，调用此接口后，任务就会被当前人领取，其他的人不再查询到待办任务",
        produces = "application/json")
    @ApiImplicitParam(name = "requestObj", dataType = "ProcessTaskReq", paramType = "body", required = true)
    @Override
    public ServiceResult claimTask(@Valid ProcessTaskReq processTaskReq) {
        ServiceResult result = new ServiceResult<>();
        try {
            processTaskModel.claimTask(processTaskReq);
        } catch (BusinessException be) {
            result.setError(be.getCode(), be.getMessage());
        } catch (Exception e) {
            IfpLogger.error(Thread.currentThread().getStackTrace()[1].getMethodName(), "执行拾取任务业务异常,case:{}",
                Throwables.getStackTraceAsString(e));
            result.setError("ECAP0000", "服务异常，请联系系统管理员");
        }
        return result;
    }

    /**
     * 归还(还原)任务，指拾取任务后的撤销操作<br />
     *
     * @param processTaskReq 任务处理请求对象: {taskId, assignee}
     * @return 转办结果标志，以success 字段值标识 true/false
     */
    @POST
    @Path("unclaim")
    @ApiOperation(value = "归还（还原）任务", notes = "拾取任务后的撤销操作，与拾取认领是一对服务配合使用", produces = "application/json")
    @ApiImplicitParam(name = "requestObj", dataType = "ProcessTaskReq", paramType = "body", required = true)
    @Override
    public ServiceResult unclaimTask(ProcessTaskReq processTaskReq) {
        ServiceResult result = new ServiceResult<>();
        try {
            processTaskModel.restoreTask(processTaskReq);
        } catch (BusinessException be) {
            result.setError(be.getCode(), be.getMessage());
        } catch (Exception e) {
            IfpLogger.error(Thread.currentThread().getStackTrace()[1].getMethodName(), "执行还原任务业务异常,case:{}",
                Throwables.getStackTraceAsString(e));
            result.setError("ECAP0000", "服务异常，请联系系统管理员");
        }
        return result;
    }

    /**
     * 根据任务ID、任务处理人查询任务详情信息
     *
     * @param taskDetailReq 任务处理请求对象: {taskId}
     * @return 任务详情信息
     */
    @POST
    @Path("detail")
    @ApiOperation(value = "查询任务详情信息", notes = "根据任务ID查询任务详情信息，这里指的是已经完成或正在审批的任务节点", produces = "application/json")
    @ApiImplicitParam(name = "requestObj", dataType = "QueryTaskDetailReq", paramType = "body", required = true)
    @Override
    public ServiceResult<TaskDTO> getTask(QueryTaskDetailReq taskDetailReq) {
        ServiceResult<TaskDTO> result = new ServiceResult<>();
        try {
            TaskDTO task = processTaskModel.getTask(taskDetailReq);
            result.setResult(task);
        } catch (BusinessException be) {
            result.setError(be.getCode(), be.getMessage());
        } catch (Exception e) {
            IfpLogger.error(Thread.currentThread().getStackTrace()[1].getMethodName(), "查询任务详情异常, case: {}",
                Throwables.getStackTraceAsString(e));
            result.setError("ECAP0000", "服务异常，请联系系统管理员");
        }
        return result;
    }

    /**
     * 审核任务、完成任务
     *
     * @param completeTaskReq 完成任务请求对象
     * @return 审核结果标志，以success 字段值标识 true/false
     */
    @POST
    @Path("complete")
    @ApiOperation(value = "审核任务（审批节点审批结果提交）", notes = "审核（完成）任务，当前节点进行审批流过提交都是调用此接口", produces = "application/json")
    @ApiImplicitParam(name = "requestObj", dataType = "CompleteTaskReq", paramType = "body", required = true)
    @Override
    public ServiceResult completeTask(CompleteTaskReq completeTaskReq) {
        ServiceResult<Object> result = new ServiceResult<>();
        try {
            processTaskModel.completeTask(completeTaskReq);
            // 发送 dingtalk 通知
            processTaskModel.sendDingtalkNotification(completeTaskReq.getTaskId(),
                ObjectUtil.objectToString(completeTaskReq.getOperationUserId()));
        } catch (BusinessException be) {
            result.setError(be.getCode(), be.getMessage());
        } catch (Exception e) {
            IfpLogger.error(Thread.currentThread().getStackTrace()[1].getMethodName(), "审核任务异常, case: {}",
                Throwables.getStackTraceAsString(e));
            result.setError("ECAP0000", "服务异常，请联系系统管理员");
        }
        return result;
    }

    /**
     * 自定义任务节点跳转 <br />
     * 会签、并行任务场景，会有问题
     *
     * @param recallTaskReq 任务跳转请求对象
     * @return 跳转处理结果
     */
    @POST
    @Path("jump")
    @ApiOperation(value = "自定义任务节点跳转",
        notes = "自定义任务节点跳转，根据流程节点id，随意进行审批流程节点跳转（前提是需要知道流程节点 id），另外会在目标任务节点添加内置变量：<br>“flow_from_task_definition_key”，用于记录是从哪个节点跳转至该节点 <br >"
            + "“flow_from_task_operate”，用于记录跳转至该节点时的操作，本接口中该值为: 6 <br >",
        produces = "application/json")
    @ApiImplicitParam(name = "requestObj", dataType = "RecallTaskReq", paramType = "body", required = true)
    @Override
    public ServiceResult customNodeJump(RecallTaskReq recallTaskReq) {
        ServiceResult<Object> result = new ServiceResult<>();
        try {
            // add by liwq on 2021-03-23 start
            // 将业务数据、流程摘要、发起人等字段放到流程变量里。（这里将代码放到service层处理，否则改动太大）
            Map<String, Object> processVariables = new HashMap<>();
            // 业务数据
            List<BusinessModuleData> businessModuleData = recallTaskReq.getBusinessData();
            // 若是传空数组过来，就认为是要赋值空数组给变量池
            if (businessModuleData != null && businessModuleData.size() == 0) {
                processVariables.put(WorkflowConstants.FLOW_BUSINESS_DATA, recallTaskReq.getBusinessData());
            }
            // 若是传null过来，就不做处理。不为null并且数组大于0，校验之后，才放入变量池
            if (businessModuleData != null && businessModuleData.size() > 0) {
                processRuntimeModel.validBusinessData(businessModuleData);
                List<BusinessModuleData> sortList = processRuntimeModel.sortBusinessData(businessModuleData);
                processVariables.put(WorkflowConstants.FLOW_BUSINESS_DATA, sortList);
            }
            // 流程摘要
            if (!StringUtils.isEmpty(recallTaskReq.getProcessRemark())) {
                processVariables.put(WorkflowConstants.FLOW_BUSINESS_SUMMARY, recallTaskReq.getProcessRemark());
            }
            // 金控经办人员
            if (!StringUtils.isEmpty(recallTaskReq.getJinKongHandling())) {
                processVariables.put(WorkflowConstants.FLOW_BUSINESS_QDPF_OPERATOR, recallTaskReq.getJinKongHandling());
                // 金控经办人员姓名
                String qdpfOperatorName = null;
                UserBaseInformationDto base = null;
                List<UserInfoDto> userInfo =
                    userCenterModel.queryUserInfo(String.valueOf(recallTaskReq.getJinKongHandling()),
                        recallTaskReq.getChannel(), String.valueOf(recallTaskReq.getOperationUserId()));
                if (userInfo != null && userInfo.size() > 0) {
                    base = userInfo.get(0).getUserBaseInformationDto();
                    if (base == null || !"1".equals(base.getUserType())) {
                        throw new BusinessException("金控经办人员不存在", "ECAP0509");
                    }
                    qdpfOperatorName = base.getUserName();
                    processVariables.put(WorkflowConstants.FLOW_BUSINESS_QDPF_OPERATOR_NAME, qdpfOperatorName);
                    // 金控经办人员钉钉ID
                    if (StringUtils.isNotEmpty(base.getDingtalkUserid())) {
                        processVariables.put(WorkflowConstants.FLOW_BUSINESS_QDPF_DINGTALK_USERID,
                            base.getDingtalkUserid());
                    }
                } else {
                    throw new BusinessException("金控经办人员不存在", "ECAP0509");
                }
            }
            // 业务场景
            if (!StringUtils.isEmpty(recallTaskReq.getBusinessScene())) {
                processVariables.put(WorkflowConstants.FLOW_BUSINESS_SCENE, recallTaskReq.getBusinessScene());
            }
            // add by liwq on 2021-03-23 end
            // add by syf on 2023-03-08 start
            // 公司名称
            if (StringUtils.isNotEmpty(recallTaskReq.getCompanyName())) {
                processVariables.put(WorkflowConstants.FLOW_COMPANY_NAME, recallTaskReq.getCompanyName());
            }
            // 产品名称
            if (StringUtils.isNotEmpty(recallTaskReq.getProductName())) {
                processVariables.put(WorkflowConstants.FLOW_PRODUCT_NAME, recallTaskReq.getProductName());
            }
            // 添加审核附件信息列表
            ArCommentExt arCommentExt = new ArCommentExt();
            arCommentExt.setOperateType(String.valueOf(recallTaskReq.getJumpPurpose()));
            if (StringUtils.isNotBlank(recallTaskReq.getAssignee())) {
                Integer assignee = userCenterModel.getUserId(recallTaskReq.getAssignee());
                arCommentExt.setAssignee(assignee);
                UserBaseInformationDto base = null;
                List<UserInfoDto> userInfo = userCenterModel.queryUserInfo(recallTaskReq.getAssignee(),
                    recallTaskReq.getChannel(), String.valueOf(recallTaskReq.getOperationUserId()));
                if (userInfo != null && userInfo.size() > 0) {
                    base = userInfo.get(0).getUserBaseInformationDto();
                    if (base == null) {
                        throw new BusinessException("任务处理人不存在", "ECAP0509");
                    }
                    arCommentExt.setAssigneeName(base.getUserName());
                }
            }
            List<CommentFile> commentFiles = recallTaskReq.getCommentFiles();
            arCommentExt.setFiles(commentFiles != null ? JSON.toJSONString(commentFiles) : null);
            arCommentExt.setCreateBy(recallTaskReq.getOperationUserId());
            arCommentExt.setGmtCreate(LocalDateTime.now());
            arCommentExt.setModifiedBy(recallTaskReq.getOperationUserId());
            arCommentExt.setGmtModified(LocalDateTime.now());
            // add by syf on 2023-03-08 end
            processTaskModel.nodeJump(recallTaskReq.getCurrentTaskId(), recallTaskReq.getTargetTaskKeyId(),
                recallTaskReq.getAssignee(), recallTaskReq.getReason(), OperatingTypeEnum.ROTATE,
                recallTaskReq.getJumpPurpose(), recallTaskReq.getVariables(), processVariables, arCommentExt);

            // 发送 dingtalk 通知
            processTaskModel.sendDingtalkNotification(recallTaskReq.getCurrentTaskId(),
                ObjectUtil.objectToString(recallTaskReq.getOperationUserId()));
        } catch (BusinessException be) {
            result.setError(be.getCode(), be.getMessage());
        } catch (Exception e) {
            IfpLogger.error(Thread.currentThread().getStackTrace()[1].getMethodName(), "自定义任务节点跳转异常, case: {}",
                Throwables.getStackTraceAsString(e));
            result.setError("ECAP0000", "服务异常，请联系系统管理员");
        }
        return result;
    }

    /**
     * 退回-任务退回至发起人<br />
     *
     * @param recallTaskReq 任务跳转请求对象
     * @return 退回处理结果
     */
    @POST
    @Path("return")
    @ApiOperation(value = "退回申请",
        notes = "任务退回至发起人，并可记录当前退回节点信息，被退回人重新提交后可以重新提交到退回人，或者重新再次走审批流程提交到下一节点<br>另外会在目标任务节点添加内置变量：<br>“flow_from_task_definition_key”，用于记录是从哪个节点退回至该节点 <br > “flow_from_task_operate”，用于记录退回至该节点时的操作，该接口中本值为: 3 <br >",
        produces = "application/json")
    @ApiImplicitParam(name = "requestObj", dataType = "RecallTaskReq", paramType = "body", required = true)
    @Override
    public ServiceResult recallBackToStartUserTask(RecallTaskReq recallTaskReq) {
        ServiceResult<Object> result = new ServiceResult<>();
        try {
            // add by syf on 2023-03-08 start
            // 将公司名称和产品名称字段放到流程变量里。（这里将代码放到service层处理，否则改动太大）
            Map<String, Object> processVariables = new HashMap<>();
            // 公司名称
            if (StringUtils.isNotEmpty(recallTaskReq.getCompanyName())) {
                processVariables.put(WorkflowConstants.FLOW_COMPANY_NAME, recallTaskReq.getCompanyName());
            }
            // 产品名称
            if (StringUtils.isNotEmpty(recallTaskReq.getProductName())) {
                processVariables.put(WorkflowConstants.FLOW_PRODUCT_NAME, recallTaskReq.getProductName());
            }
            // 添加审核附件信息列表
            ArCommentExt arCommentExt = new ArCommentExt();
            arCommentExt.setOperateType(String.valueOf(recallTaskReq.getJumpPurpose()));
            if (StringUtils.isNotBlank(recallTaskReq.getAssignee())) {
                Integer assignee = userCenterModel.getUserId(recallTaskReq.getAssignee());
                arCommentExt.setAssignee(assignee);
                UserBaseInformationDto base = null;
                List<UserInfoDto> userInfo = userCenterModel.queryUserInfo(recallTaskReq.getAssignee(),
                    recallTaskReq.getChannel(), String.valueOf(recallTaskReq.getOperationUserId()));
                if (userInfo != null && userInfo.size() > 0) {
                    base = userInfo.get(0).getUserBaseInformationDto();
                    if (base == null) {
                        throw new BusinessException("任务处理人不存在", "ECAP0509");
                    }
                    arCommentExt.setAssigneeName(base.getUserName());
                }
            }
            List<CommentFile> commentFiles = recallTaskReq.getCommentFiles();
            arCommentExt.setFiles(commentFiles != null ? JSON.toJSONString(commentFiles) : null);
            arCommentExt.setCreateBy(recallTaskReq.getOperationUserId());
            arCommentExt.setGmtCreate(LocalDateTime.now());
            arCommentExt.setModifiedBy(recallTaskReq.getOperationUserId());
            arCommentExt.setGmtModified(LocalDateTime.now());
            // add by syf on 2023-03-10 end
            processTaskModel.nodeJumpToFirstTask(recallTaskReq.getCurrentTaskId(), recallTaskReq.getAssignee(),
                recallTaskReq.getReason(), recallTaskReq.getVariables(), processVariables, arCommentExt);
        } catch (BusinessException be) {
            result.setError(be.getCode(), be.getMessage());
        } catch (Exception e) {
            IfpLogger.error(Thread.currentThread().getStackTrace()[1].getMethodName(), "退回-任务退回至发起人异常, case: {}",
                Throwables.getStackTraceAsString(e));
            result.setError("ECAP0000", "服务异常，请联系系统管理员");
        }
        return result;
    }

    /**
     * 驳回-任务退回至上一任务 <br />
     * 会签、并行任务场景，会有问题
     * 
     * @param recallTaskReq 任务跳转请求对象
     * @return 跳转处理结果
     */
    @POST
    @Path("reject")
    @ApiOperation(value = "驳回任务",
        notes = "驳回-任务退回至上一任务（会签、并行任务无法使用）<br>另外会在目标任务节点添加内置变量：<br>“flow_from_task_definition_key”，用于记录是从哪个节点驳回至该节点 <br > “flow_from_task_operate”，用于记录驳回至该节点时的操作，该接口中本值为: 2 <br >",
        produces = "application/json")
    @ApiImplicitParam(name = "requestObj", dataType = "RecallTaskReq", paramType = "body", required = true)
    @Override
    public ServiceResult rejectToPrevUserTask(RecallTaskReq recallTaskReq) {
        ServiceResult<Object> result = new ServiceResult<>();
        try {
            processTaskModel.nodeJumpToPrevTask(recallTaskReq.getCurrentTaskId(), recallTaskReq.getAssignee(),
                recallTaskReq.getReason(), recallTaskReq.getVariables());
        } catch (BusinessException be) {
            result.setError(be.getCode(), be.getMessage());
        } catch (Exception e) {
            IfpLogger.error(Thread.currentThread().getStackTrace()[1].getMethodName(), "驳回-任务退回至上一任务异常, case: {}",
                Throwables.getStackTraceAsString(e));
            result.setError("ECAP0000", "服务异常，请联系系统管理员");
        }
        return result;
    }

    /**
     *
     * @param withDrawTaskReq 撤回任务请求对象
     * @return 撤回任务处理结果
     */
    @POST
    @Path("withDrawTask")
    @ApiOperation(value = "撤回任务", notes = "撤回任务", produces = "application/json")
    @ApiImplicitParam(name = "requestObj", dataType = "WithDrawTaskReq", paramType = "body", required = true)
    @Override
    public ServiceResult withDrawTask(WithDrawTaskReq withDrawTaskReq) {
        ServiceResult<Object> result = new ServiceResult<>();
        try {
            processTaskModel.withDrawTask(withDrawTaskReq);
        } catch (BusinessException be) {
            result.setError(be.getCode(), be.getMessage());
        } catch (Exception e) {
            IfpLogger.error(Thread.currentThread().getStackTrace()[1].getMethodName(), "驳回-任务退回至上一任务异常, case: {}",
                Throwables.getStackTraceAsString(e));
            result.setError("ECAP0000", "服务异常，请联系系统管理员");
        }
        return result;
    }

    /**
     * 委派任务
     *
     * @param transferTaskReq 委派任务请求对象: {taskId, receiver}
     * @return 转办结果标志，以success 字段值标识 true/false
     */
    @POST
    @Path("delegate")
    @ApiOperation(value = "委派任务", notes = "委派指定操作人办理任务，任务办理完成后需要调用（委派任务归还服务）任务重新回归委派人，委派人同意后，审批流程继续，如果不归还任务，审批流程无法继续。",
        produces = "application/json")
    @ApiImplicitParam(name = "requestObj", dataType = "TransferTaskReq", paramType = "body", required = true)
    @Override
    public ServiceResult delegateTask(TransferTaskReq transferTaskReq) {
        ServiceResult result = new ServiceResult<>();
        try {
            processTaskModel.delegateTask(transferTaskReq);
        } catch (BusinessException be) {
            result.setError(be.getCode(), be.getMessage());
        } catch (Exception e) {
            IfpLogger.error(Thread.currentThread().getStackTrace()[1].getMethodName(), "执行委派任务业务异常,case:{}",
                Throwables.getStackTraceAsString(e));
            result.setError("ECAP0000", "服务异常，请联系系统管理员");
        }
        return result;
    }

    /**
     * 委派任务归还
     *
     * @param resolveTaskReq 委派任务归还请求对象: {taskId, variables}
     * @return 转办结果标志，以success 字段值标识 true/false
     */
    @POST
    @Path("resolve")
    @ApiOperation(value = "委派任务归还", notes = "被委派人任务办理完成后，将任务回归至委派人，与委派任务是一组接口相互配合使用", produces = "application/json")
    @ApiImplicitParam(name = "requestObj", dataType = "TransferTaskReq", paramType = "body", required = true)
    @Override
    public ServiceResult resolveTask(ResolveTaskReq resolveTaskReq) {
        ServiceResult result = new ServiceResult<>();
        try {
            processTaskModel.resolveTask(resolveTaskReq);
        } catch (BusinessException be) {
            result.setError(be.getCode(), be.getMessage());
        } catch (Exception e) {
            IfpLogger.error(Thread.currentThread().getStackTrace()[1].getMethodName(), "执行归还委派任务业务异常,case:{}",
                Throwables.getStackTraceAsString(e));
            result.setError("ECAP0000", "服务异常，请联系系统管理员");
        }
        return result;
    }

    /**
     * 根据当前任务 id 查询下一个任务节点信息
     *
     * @param taskDetailReq 查询任务详情信息请求对象，使用当前任务 id
     * @return 下一个任务节点
     */
    @POST
    @Path("get-next-task")
    @ApiOperation(value = "查询下一个任务节点信息", notes = "根据当前任务 id 查询下一个任务节点信息", produces = "application/json")
    @ApiImplicitParam(name = "requestObj", dataType = "QueryTaskDetailReq", paramType = "body", required = true)
    @Override
    public ServiceResult<NextTaskDTO> getNextTask(QueryTaskDetailReq taskDetailReq) {
        ServiceResult<NextTaskDTO> result = new ServiceResult<>();
        try {
            result.setResult(processTaskModel.getNextUserTask(taskDetailReq.getTaskId()));
        } catch (BusinessException be) {
            result.setError(be.getCode(), be.getMessage());
        } catch (Exception e) {
            IfpLogger.error(Thread.currentThread().getStackTrace()[1].getMethodName(), "查询下一个任务节点信息服务异常,case:{}",
                Throwables.getStackTraceAsString(e));
            result.setError("ECAP0000", "服务异常，请联系系统管理员");
        }
        return result;
    }

    /**
     * 根据任务 id 和用户 id 查询用户是否有处理该任务的处理权限
     *
     * @param req 任务处理请求对象
     * @return 结果标志，以success 字段值标识 true/false
     */
    @Override
    public ServiceResult<Boolean> checkTaskPermission(ProcessTaskReq req) {
        ServiceResult<Boolean> result = new ServiceResult<>();
        try {
            result.setResult(processTaskModel.checkTaskPermission(req));
        } catch (BusinessException be) {
            result.setError(be.getCode(), be.getMessage());
        } catch (Exception e) {
            IfpLogger.error(Thread.currentThread().getStackTrace()[1].getMethodName(), "查询用户是否有处理任务的处理权限服务异常,case:{}",
                Throwables.getStackTraceAsString(e));
            result.setError("ECAP0000", "服务异常，请联系系统管理员");
        }
        return result;
    }

}
